
import {orthographicProjection} from "../projection/orthographic.js";
import {buildScaleFromSegments} from "../palette/palette.js";
import {regularGrid} from "../grid/regular.js";
import {vector} from "../interpolate/bilinear.js";
import {buildFastoverlay} from "./fastoverlay.js";
import * as twod from "../canvas/twod.js";
// import * as d3 from "../lib/d3.js";
import * as d3 from "d3";
import {GLU} from "./glu.js";
import {arraysEq} from "../util/arrays.js";


const width = 300, height = 300, pixelRatio = 1;
const proj = orthographicProjection(width / 2, 0, 0, width / 2, width / 2);
const grid = regularGrid({"start": 0, "delta": 120, "size": 3}, {"start": 60, "delta": -60, "size": 3});
const data = new Float32Array([
//  u  v     len
    1, 0,  // 1
    2, 0,  // 2
    3, 0,  // 3
    4, 0,  // 4
    5, 0,  // 5
    8, 0,  // 8
    6, 0,  // 6
    8, 0,  // 8
    NaN, NaN,
]);
const field = vector(grid, data);
const scale = buildScaleFromSegments([0, 7], [
    [0, [255, 255, 255]],
    [1, [  0,   0, 255]],
    [2, [  0, 255,   0]],
    [3, [  0, 255, 255]],
    [4, [255,   0,   0]],
    [5, [255,   0, 255]],
    [6, [255, 255,   0]],
    [7, [255, 255, 255]],
], 8);

function sample(gl, x, y) {
    const out = new Uint8Array(4);
    gl.readPixels(x, y, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, out);
    return out;
}

export function runTest(show) {
    console.time("glTest");
    const res = {pass: false};
    try {
        const canvas = twod.createCanvas(width, height);
        if (show) {
            d3.select(canvas)
                .style("width", `${width / pixelRatio}px`)
                .style("height", `${height / pixelRatio}px`)
                .style("position", "absolute")
                .style("top", "0")
                .style("left", "0");
            d3.select("#display").node().appendChild(canvas);
        }

        const gl = GLU.getWebGL(canvas);
        if (!gl) {
            res.hasContext = false;
            return res;
        }

        const maxTexSize = +gl.getParameter(gl.MAX_TEXTURE_SIZE) || -1;
        if (maxTexSize < 4096) {
            res.maxTexSize = maxTexSize;  // data layers up to this size are expected.
            return res;
        }

        const precision = +gl.getShaderPrecisionFormat(gl.FRAGMENT_SHADER, gl.HIGH_FLOAT).precision || -1;
        if (precision < 23) {
            res.precision = precision;  // not enough precision for expected data layers.
            return res;
        }

        res.scenario = 1;
        const drawResult = buildFastoverlay(
            canvas,
            undefined,
            () => 1,
            () => ({width, height, pixelRatio}),
            (glu) => [proj.webgl(glu), grid.webgl(glu), field.webgl(glu), scale.webgl(glu)],
        ).draw();
        if (drawResult.err) {
            res.err = drawResult.err;
            return res;
        }

        const colorMatch = [
            arraysEq(sample(gl, 195, 300 -  20), [  0,   0, 255, 255]),
            arraysEq(sample(gl, 195, 300 -  48), [  0, 255,   0, 255]),
            arraysEq(sample(gl, 195, 300 -  90), [  0, 255, 255, 255]),
            arraysEq(sample(gl, 195, 300 - 150), [255,   0,   0, 255]),
            arraysEq(sample(gl, 195, 300 - 200), [255,   0, 255, 255]),
            arraysEq(sample(gl, 195, 300 - 260), [255, 255,   0, 255]),
            arraysEq(sample(gl, 195, 300 - 285), [255, 255, 255, 255]),
            arraysEq(sample(gl, 145, 300 - 285), [  0,   0,   0,   0]),
        ];
        if (colorMatch.some(e => e === false)) {
            res.colorMatch = colorMatch;  // the expected rendering is wrong so this webgl implementation is suspect.
            return res;
        }

        const err = gl.getError();
        if (err !== 0) {
            res.err = err;
        } else {
            res.pass = true;
        }
    } catch (e) {
        console.error(e);
        res.err = e.toString();
    } finally {
        console.timeEnd("glTest");
    }
    return res;
}
